package com.gitee.wsl.ext.number

import kotlin.math.absoluteValue

fun floorMultiple(source: Int, multiple: Int) = when {
    source > 0 -> source - source % multiple
    else -> {
        val tmp = source + 1
        tmp - tmp % multiple - multiple
    }
}

fun ceilMultiple(source: Float, multiple: Float) =
    if (source > 0) source + (multiple - source % multiple)
    else source - source % multiple


fun ceilMultiple(source: Double, multiple: Double) =
    if (source > 0) source + (multiple - source % multiple)
    else source - source % multiple


fun ceilMultiple(source: Int, multiple: Int) =
    if (source > 0) {
        val tmp = source - 1
        tmp + (multiple - tmp % multiple)
    } else source - source % multiple


fun Double.closestMultipleOf(multiple: Double): Double {
    val prev = prevMultipleOf(multiple)
    val next = nextMultipleOf(multiple)
    return if ((this - prev).absoluteValue < (this - next).absoluteValue) prev else next
}
fun Int.closestMultipleOf(multiple: Int): Int {
    val prev = prevMultipleOf(multiple)
    val next = nextMultipleOf(multiple)
    return if ((this - prev).absoluteValue < (this - next).absoluteValue) prev else next
}
fun Long.closestMultipleOf(multiple: Long): Long {
    val prev = prevMultipleOf(multiple)
    val next = nextMultipleOf(multiple)
    return if ((this - prev).absoluteValue < (this - next).absoluteValue) prev else next
}

fun Double.nextMultipleOf(multiple: Double) = if (this.isMultipleOf(multiple)) this else (((this / multiple) + 1) * multiple)
fun Int.nextMultipleOf(multiple: Int) = if (this.isMultipleOf(multiple)) this else (((this / multiple) + 1) * multiple)
fun Long.nextMultipleOf(multiple: Long) = if (this.isMultipleOf(multiple)) this else (((this / multiple) + 1) * multiple)

fun Double.prevMultipleOf(multiple: Double) = if (this.isMultipleOf(multiple)) this else nextMultipleOf(multiple) - multiple
fun Int.prevMultipleOf(multiple: Int) = if (this.isMultipleOf(multiple)) this else nextMultipleOf(multiple) - multiple
fun Long.prevMultipleOf(multiple: Long) = if (this.isMultipleOf(multiple)) this else nextMultipleOf(multiple) - multiple

fun Double.isMultipleOf(multiple: Double) = multiple.isAlmostZero() || (this % multiple).isAlmostZero()
fun Int.isMultipleOf(multiple: Int) = multiple == 0 || (this % multiple) == 0
fun Long.isMultipleOf(multiple: Long) = multiple == 0L || (this % multiple) == 0L
